智能合约模拟调用的具体应用:在golang中查询uniswap v3智能合约上某代币的价格 您所在的位置:网站首页 usdc价格查询 uniswap api 智能合约模拟调用的具体应用:在golang中查询uniswap v3智能合约上某代币的价格

智能合约模拟调用的具体应用:在golang中查询uniswap v3智能合约上某代币的价格

2024-03-14 17:49| 来源: 网络整理| 查看: 265

一、最初的实现思路

合约的方法如果是public view的,那么通过golang代码可以直接调用,步骤大致为: 1、使用合约的ABI生成.go文件接口 2、使用以太坊节点链接初始化以太坊客户端; 3、以以太坊客户端和uniswap合约地址为参数,实例化uniswap合约 4、直接调用uniswap的“查询价格”的方法,传入代币地址和数量等参数,获取价格。

二、遇到的问题

上述思路在使用uniswap v2时是奏效的,但v3的合约代码中找不到某个方法是public view的供查询价格。 而看文档的说明,可以调用quoter合约的“quoteExactInputSingle”方法查询价格。 看合约的源码,发现该方法的调用会上链,也就是需要消耗gas。这说明代币的兑换实质发生了,而我们的需求则只是查询价格而非交易。

三、智能合约的模拟调用

在找不到其他更合适方法且无法理解quoter合约的时候,同事提出了原理和解决方案。我们可以运用智能合约模拟调用的特性,来实现只查询价格,而不改变链状态。

那么,什么是合约的模拟调用?

假设合约中有状态变量number,有方法addOne,每一次调用addOne都会给number加一,也就是改变了链上的数据状态。

我们想知道下次调用addOne会使number变为几,而不真的改变number,我们就要用“模拟调用”。

假设number目前是5,具体的实现,在js代码中是这样的:

const number= await contract.addOne.call(); //输出6,但链上仍为5

关键就在于调用了addOne方法后,又加上了.call() 这就是模拟调用。 如果不加.call,则输出6,且链上也改为了6.

四、golang是如何实现的

知道了原理,那么在golang中应该如何实现呢? 回到第一部分,有个步骤是生成.go文件。 .go文件生成后,在文件中会有UniswapRaw这样的结构体。 这就是模拟调用应该使用的结构体。 步骤是: 1、使用合约的ABI生成.go文件接口 2、使用以太坊节点链接初始化以太坊客户端; 3、以以太坊客户端和uniswap_quoter合约地址为参数,实例化uniswap_quoter合约 4、以uniswap_quoter对象为参数,实例化其对应的Raw对象rawCaller 5、声明一个空的输出变量 var out []interface{} 构造一个callOpts对象 准备业务入参params 6、调用rawCaller.Call(callOpts,out,params) 7、方法调用后,结果会写入out,而链上状态没有改变。 代码大致如下:

client := utils.GetChainClient() uniswap, _ := uniswap_factory.NewUniswapV3QuoterV2(common.HexToAddress(uniswapAddress), client) callOpt := &bind.CallOpts{ From: common.Address{}, Context: context.Background(), } token1 := common.HexToAddress("0x...") token2 = common.HexToAddress("0x...") fee := big.NewInt(3000) amountIn := utils.FloatStringToBigInt("1.00", 18) sqrtPriceLimitX96 := big.NewInt(0) var out []interface{} rawCaller := &uniswap_factory.UniswapV3QuoterV2Raw{Contract: uniswap} err := rawCaller.Call(callOpt, &out,"quoteExactInputSingle", uniswap_factory.IQuoterV2QuoteExactInputSingleParams{ TokenIn: token1, TokenOut: token2, AmountIn: amountIn, Fee: fee, SqrtPriceLimitX96: sqrtPriceLimitX96, }) if err != nil { logger.GetLogger().Errorf("get currency last price error %s", err.Error()) }else{ price := utils.ConvertDecimal(out[0].(*big.Int), consts.Erc20Decimal) fmt.Println("price get :", price) }


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有